package com.example.service.impl;

import com.example.common.PageResult;
import com.example.dto.StockOperationDTO;
import com.example.dto.StockRecordQueryDTO;
import com.example.entity.StockRecord;
import com.example.entity.SupplyProduct;
import com.example.entity.StoreInventory;
import com.example.entity.StoreProduct;
import com.example.exception.BusinessException;
import com.example.mapper.StockRecordMapper;
import com.example.mapper.SupplyProductMapper;
import com.example.mapper.StoreInventoryMapper;
import com.example.mapper.StoreProductMapper;
import com.example.service.StockRecordService;
import com.example.vo.StockRecordVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 库存记录Service实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StockRecordServiceImpl implements StockRecordService {

    private final StockRecordMapper stockRecordMapper;
    private final SupplyProductMapper supplyProductMapper;
    private final StoreInventoryMapper storeInventoryMapper;
    private final StoreProductMapper storeProductMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean stockIn(StockOperationDTO operationDTO, Long operatorId, String operatorName) {
        log.info("商品入库操作开始，供货商品ID：{}，数量：{}", operationDTO.getProductId(), operationDTO.getQuantity());

        // 1. 校验参数
        validateStockOperation(operationDTO, "IN");

        // 2. 查询供货商品信息（现在productId是供货商品ID）
        SupplyProduct supplyProduct = supplyProductMapper.selectById(operationDTO.getProductId());
        if (supplyProduct == null) {
            throw BusinessException.dataNotFound("供货商品");
        }

        // 3. 查找或创建对应的店长商品
        StoreProduct storeProduct = findOrCreateStoreProduct(supplyProduct, operatorId);
        
        // 4. 校验管理员商品库存是否充足（入库是从管理员商品中取出）
        if (supplyProduct.getStock() < operationDTO.getQuantity()) {
            throw BusinessException.dataValidationFailed("管理员商品库存不足，当前库存：" + supplyProduct.getStock());
        }

        // 5. 更新管理员商品库存（减少）
        Integer beforeSupplyStock = supplyProduct.getStock();
        Integer afterSupplyStock = beforeSupplyStock - operationDTO.getQuantity();
        supplyProduct.setStock(afterSupplyStock);
        supplyProductMapper.updateById(supplyProduct);

        // 6. 更新店长商品库存（增加）
        Integer beforeStoreStock = storeProduct.getCurrentStock();
        Integer afterStoreStock = beforeStoreStock + operationDTO.getQuantity();
        storeProductMapper.updateStock(storeProduct.getId(), afterStoreStock);

        // 7. 创建管理员出库记录（从管理员角度看是出库）
        createAdminStockOutRecord(supplyProduct, operationDTO.getQuantity(), beforeSupplyStock, afterSupplyStock, 
                "店长进货出库", operatorId, operatorName);
        
        // 8. 创建店长入库记录（从店长角度看是入库）
        createStoreStockInRecord(supplyProduct, operationDTO.getQuantity(), beforeStoreStock, afterStoreStock, 
                operationDTO.getRemark(), operatorId, operatorName);

        log.info("商品入库操作完成，商品：{}，管理员库存：{}→{}，店长商品库存：{}→{}",
                supplyProduct.getProductName(), beforeSupplyStock, afterSupplyStock, beforeStoreStock, afterStoreStock);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean stockOut(StockOperationDTO operationDTO, Long operatorId, String operatorName) {
        log.info("商品出库操作开始，商品ID：{}，数量：{}", operationDTO.getProductId(), operationDTO.getQuantity());
        
        // 1. 校验参数
        validateStockOperation(operationDTO, "OUT");
        
        // 2. 查询商品信息
        SupplyProduct product = supplyProductMapper.selectById(operationDTO.getProductId());
        if (product == null) {
            throw BusinessException.dataNotFound("商品");
        }
        
        // 3. 查询店长库存
        StoreInventory storeInventory = storeInventoryMapper.selectByManagerAndProduct(operatorId, operationDTO.getProductId());
        if (storeInventory == null || storeInventory.getCurrentStock() < operationDTO.getQuantity()) {
            int currentStock = storeInventory != null ? storeInventory.getCurrentStock() : 0;
            throw BusinessException.dataValidationFailed("店长库存不足，当前库存：" + currentStock);
        }
        
        // 4. 更新店长库存（减少）
        Integer beforeStoreStock = storeInventory.getCurrentStock();
        Integer afterStoreStock = beforeStoreStock - operationDTO.getQuantity();
        updateStoreInventory(operatorId, operationDTO.getProductId(), -operationDTO.getQuantity(), false);
        
        // 5. 创建店长出库记录
        createStoreStockOutRecord(product, operationDTO.getQuantity(), beforeStoreStock, afterStoreStock, 
                operationDTO.getRemark(), operatorId, operatorName);
        
        log.info("商品出库操作完成，商品：{}，店长库存：{}→{}", 
                product.getProductName(), beforeStoreStock, afterStoreStock);
        return true;
    }

    @Override
    public PageResult<StockRecordVO> getPageList(StockRecordQueryDTO queryDTO) {
        PageHelper.startPage(queryDTO.getPage(), queryDTO.getSize());
        // 店长查询时只查询店长相关的记录
        List<StockRecordVO> list = stockRecordMapper.selectStoreStockRecords(queryDTO);
        PageInfo<StockRecordVO> pageInfo = new PageInfo<>(list);
        
        return new PageResult<>(
                pageInfo.getPageNum(),
                pageInfo.getPageSize(),
                pageInfo.getTotal(),
                list
        );
    }

    @Override
    public List<StockRecordVO> getByProductId(Long productId) {
        return stockRecordMapper.selectByProductId(productId);
    }

    @Override
    public List<StockRecordVO> exportRecords(StockRecordQueryDTO queryDTO) {
        // 店长导出时只导出店长相关的记录
        return stockRecordMapper.selectStoreStockRecords(queryDTO);
    }

    /**
     * 校验库存操作参数
     */
    private void validateStockOperation(StockOperationDTO operationDTO, String expectedType) {
        if (operationDTO.getProductId() == null) {
            throw BusinessException.dataValidationFailed("商品ID不能为空");
        }
        if (operationDTO.getQuantity() == null || operationDTO.getQuantity() <= 0) {
            throw BusinessException.dataValidationFailed("操作数量必须大于0");
        }
        if (!expectedType.equals(operationDTO.getRecordType())) {
            throw BusinessException.dataValidationFailed("操作类型错误");
        }
    }

    /**
     * 创建库存记录
     */
    /**
     * 创建管理员出库记录
     * 当店长从管理员进货时，从管理员角度看是出库
     */
    private void createAdminStockOutRecord(SupplyProduct product, Integer quantity, 
                                          Integer beforeStock, Integer afterStock, 
                                          String remark, Long operatorId, String operatorName) {
        try {
            StockRecord stockRecord = new StockRecord();
            stockRecord.setRecordNo(generateRecordNo());
            stockRecord.setProductId(product.getId());
            stockRecord.setProductName(product.getProductName());
            stockRecord.setProductCode(product.getProductCode());
            stockRecord.setRecordType("OUT"); // 管理员出库
            stockRecord.setQuantity(quantity);
            stockRecord.setBeforeStock(beforeStock);
            stockRecord.setAfterStock(afterStock);
            stockRecord.setUnitCost(product.getCost());
            
            if (product.getCost() != null) {
                stockRecord.setTotalCost(product.getCost().multiply(new BigDecimal(quantity)));
            }
            
            stockRecord.setOperatorId(operatorId);
            stockRecord.setOperatorName(operatorName + "(管理员出库)");
            stockRecord.setRemark(remark);
            stockRecord.setCreateTime(LocalDateTime.now());
            stockRecord.setUpdateTime(LocalDateTime.now());
            stockRecord.setDeleted(0);
            
            stockRecordMapper.insert(stockRecord);
            log.info("创建管理员出库记录成功，商品: {}, 数量: {}", product.getProductName(), quantity);
        } catch (Exception e) {
            log.error("创建管理员出库记录失败", e);
        }
    }
    
    /**
     * 创建店长入库记录
     * 当店长从管理员进货时，从店长角度看是入库
     */
    private void createStoreStockInRecord(SupplyProduct product, Integer quantity, 
                                         Integer beforeStock, Integer afterStock, 
                                         String remark, Long operatorId, String operatorName) {
        try {
            StockRecord stockRecord = new StockRecord();
            stockRecord.setRecordNo(generateRecordNo());
            stockRecord.setProductId(product.getId());
            stockRecord.setProductName(product.getProductName());
            stockRecord.setProductCode(product.getProductCode());
            stockRecord.setRecordType("IN"); // 店长入库
            stockRecord.setQuantity(quantity);
            stockRecord.setBeforeStock(beforeStock);
            stockRecord.setAfterStock(afterStock);
            stockRecord.setUnitCost(product.getCost());
            
            if (product.getCost() != null) {
                stockRecord.setTotalCost(product.getCost().multiply(new BigDecimal(quantity)));
            }
            
            stockRecord.setOperatorId(operatorId);
            stockRecord.setOperatorName(operatorName + "(店长入库)");
            stockRecord.setRemark(remark != null ? remark : "从管理员进货");
            stockRecord.setCreateTime(LocalDateTime.now());
            stockRecord.setUpdateTime(LocalDateTime.now());
            stockRecord.setDeleted(0);
            
            stockRecordMapper.insert(stockRecord);
            log.info("创建店长入库记录成功，商品: {}, 数量: {}", product.getProductName(), quantity);
        } catch (Exception e) {
            log.error("创建店长入库记录失败", e);
        }
    }
    
    /**
     * 创建店长出库记录
     * 当店长直接出库时使用
     */
    private void createStoreStockOutRecord(SupplyProduct product, Integer quantity, 
                                          Integer beforeStock, Integer afterStock, 
                                          String remark, Long operatorId, String operatorName) {
        try {
            StockRecord stockRecord = new StockRecord();
            stockRecord.setRecordNo(generateRecordNo());
            stockRecord.setProductId(product.getId());
            stockRecord.setProductName(product.getProductName());
            stockRecord.setProductCode(product.getProductCode());
            stockRecord.setRecordType("OUT"); // 店长出库
            stockRecord.setQuantity(quantity);
            stockRecord.setBeforeStock(beforeStock);
            stockRecord.setAfterStock(afterStock);
            stockRecord.setUnitCost(product.getCost());
            
            if (product.getCost() != null) {
                stockRecord.setTotalCost(product.getCost().multiply(new BigDecimal(quantity)));
            }
            
            stockRecord.setOperatorId(operatorId);
            stockRecord.setOperatorName(operatorName + "(店长出库)");
            stockRecord.setRemark(remark != null ? remark : "店长直接出库");
            stockRecord.setCreateTime(LocalDateTime.now());
            stockRecord.setUpdateTime(LocalDateTime.now());
            stockRecord.setDeleted(0);
            
            stockRecordMapper.insert(stockRecord);
            log.info("创建店长出库记录成功，商品: {}, 数量: {}", product.getProductName(), quantity);
        } catch (Exception e) {
            log.error("创建店长出库记录失败", e);
        }
    }

    /**
     * 查找或创建店长商品
     */
    private StoreProduct findOrCreateStoreProduct(SupplyProduct supplyProduct, Long storeManagerId) {
        // 先查找是否已存在对应的店长商品
        StoreProduct existingProduct = storeProductMapper.selectByStoreManagerAndSupplyProduct(storeManagerId, supplyProduct.getId());

        if (existingProduct != null) {
            return existingProduct;
        }

        // 如果不存在，则自动创建一个新的店长商品
        StoreProduct newStoreProduct = new StoreProduct();
        newStoreProduct.setStoreManagerId(storeManagerId);
        newStoreProduct.setSupplyProductId(supplyProduct.getId());
        newStoreProduct.setProductName(supplyProduct.getProductName());
        newStoreProduct.setProductCode(supplyProduct.getProductCode());
        newStoreProduct.setModel(supplyProduct.getModel());
        newStoreProduct.setSellingPrice(supplyProduct.getCost().multiply(new BigDecimal("1.2"))); // 默认成本价的1.2倍
        newStoreProduct.setCurrentStock(0); // 初始库存为0
        newStoreProduct.setMinStock(10); // 默认最低库存预警为10
        newStoreProduct.setStatus(0); // 默认下架状态，需要通过商品上架管理手动上架
        newStoreProduct.setCreateTime(LocalDateTime.now());
        newStoreProduct.setUpdateTime(LocalDateTime.now());
        newStoreProduct.setDeleted(0);

        storeProductMapper.insert(newStoreProduct);
        log.info("自动创建店长商品，供货商品ID：{}，店长商品ID：{}", supplyProduct.getId(), newStoreProduct.getId());

        return newStoreProduct;
    }

    /**
     * 生成记录编号
     */
    private String generateRecordNo() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));
        return "SR" + timestamp + random;
    }

    /**
     * 更新店长库存
     */
    private void updateStoreInventory(Long storeManagerId, Long productId, Integer quantity, boolean isIn) {
        // 查询是否已存在库存记录
        StoreInventory existing = storeInventoryMapper.selectByManagerAndProduct(storeManagerId, productId);
        
        if (existing == null) {
            // 创建新的库存记录
            StoreInventory newInventory = new StoreInventory();
            newInventory.setStoreManagerId(storeManagerId);
            newInventory.setProductId(productId);
            newInventory.setCurrentStock(Math.max(0, quantity)); // 确保库存不为负数
            newInventory.setTotalIn(isIn ? quantity : 0);
            newInventory.setTotalOut(isIn ? 0 : Math.abs(quantity)); // 出库数量用绝对值
            newInventory.setCreateTime(LocalDateTime.now());
            newInventory.setUpdateTime(LocalDateTime.now());
            newInventory.setDeleted(0);
            
            storeInventoryMapper.insert(newInventory);
        } else {
            // 更新现有库存记录
            storeInventoryMapper.updateStock(storeManagerId, productId, quantity, isIn);
        }
    }
} 